// 2025/3/4: 首个版本
// 2025/8/29: 确认过程支持默认值

using System;
using System.Collections.Generic;
using System.IO;
using ASEva;

namespace RemoteConsole
{
    enum LocalFileChooserType
    {
        OpenFile,
        SaveFile,
        Folder,
    }

    class LocalFileChooser
    {
        public LocalFileChooserType Type { get; set; }
        public String[] OpenFilter { get; set; } // OpenFile时有效
        public String SaveSuffix { get; set; } // SaveFile时有效

        public bool Choose(ConsoleIO io, out string result)
        {
            result = null;

            // 初始位置
            String curDir = null;
            {
                var homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

                var options = new List<String>();
                var optionDirs = new List<String>();
                options.Add(chinese ? "取消" : "Cancel"); optionDirs.Add(null);
                options.Add(homePath + (chinese ? " (用户目录)" : " (User home)")); optionDirs.Add(homePath);
                options.Add(desktopPath + (chinese ? " (桌面)" : " (Desktop)")); optionDirs.Add(desktopPath);
                foreach (var drive in DriveInfo.GetDrives())
                {
                    if (drive.DriveType == DriveType.NoRootDirectory) continue;

                    var driveDir = drive.Name;
                    var driveLabel = drive.VolumeLabel;
                    var separatorIndex = driveLabel.LastIndexOf(Path.DirectorySeparatorChar);
                    if (separatorIndex >= 0 && separatorIndex + 1 < driveLabel.Length) driveLabel = driveLabel.Substring(separatorIndex + 1);
                    var driveTitle = driveDir + " (" + driveLabel + ")";

                    if (APIInfo.GetRunningOS() == "windows")
                    {
                        options.Add(driveTitle);
                        optionDirs.Add(driveDir);
                    }
                    else
                    {
                        if (driveDir == "/") options.Add(driveDir + (chinese ? " (根路径)" : " (Root path)"));
                        else if (driveDir.StartsWith("/media/")) options.Add(driveTitle);
                        else if (driveDir.StartsWith("/Volumes/")) options.Add(driveTitle);
                        else continue;
                        optionDirs.Add(driveDir);
                    }
                }

                int startLocIndex = 0;
                if (!io.SingleSelect(chinese ? "请选择初始位置" : "Select the initial location", options.ToArray(), ref startLocIndex)) return false;
                curDir = optionDirs[startLocIndex];
            }
            if (curDir == null) return true;

            // 循环选择
            var cancelID = "/\\cancel/\\";
            var newFileID = "/\\new-file/\\";
            var newDirID = "/\\new-dir/\\";
            var selectDirID = "/\\select-dir/\\";
            while (true)
            {
                var options = new List<String>();
                var optionPath = new List<String>();
                var curDirWithSeparator = curDir;
                if (!curDirWithSeparator.EndsWith(Path.DirectorySeparatorChar)) curDirWithSeparator += Path.DirectorySeparatorChar;
                var curDirLength = curDirWithSeparator.Length;

                options.Add(chinese ? "取消" : "Cancel");
                optionPath.Add(cancelID);

                if (Type == LocalFileChooserType.SaveFile)
                {
                    options.Add(chinese ? "新建文件" : "New file");
                    optionPath.Add(newFileID);
                }

                if (Type == LocalFileChooserType.Folder)
                {
                    options.Add(chinese ? "选择当前文件夹" : "Select current folder");
                    optionPath.Add(selectDirID);
                }

                if (Type == LocalFileChooserType.SaveFile || Type == LocalFileChooserType.Folder)
                {
                    options.Add(chinese ? "新建文件夹" : "New folder");
                    optionPath.Add(newDirID);
                }

                var parentDir = Path.GetDirectoryName(curDir);
                if (parentDir != null)
                {
                    options.Add(chinese ? "上级文件夹" : "Parent folder");
                    optionPath.Add(parentDir);
                }

                var buf = new List<String>();
                foreach (var dir in Directory.GetDirectories(curDir))
                {
                    var name = dir.Substring(curDirLength);
                    if (name.StartsWith('.') || name.StartsWith('$')) continue;
                    buf.Add(dir);
                }
                buf.Sort();
                foreach (var dir in buf)
                {
                    var name = dir.Substring(curDirLength);
                    options.Add((chinese ? "进入文件夹: " : "Enter folder: ") + name);
                    optionPath.Add(dir);
                }

                if (Type == LocalFileChooserType.OpenFile || Type == LocalFileChooserType.SaveFile)
                {
                    var exts = new List<String>();
                    if (Type == LocalFileChooserType.OpenFile)
                    {
                        if (OpenFilter != null)
                        {
                            foreach (var ext in OpenFilter) exts.Add(ext.ToLower());
                        }
                    }
                    else
                    {
                        if (SaveSuffix != null) exts.Add(SaveSuffix.ToLower());
                    }

                    buf.Clear();
                    foreach (var file in Directory.GetFiles(curDir))
                    {
                        var name = file.Substring(curDirLength);
                        if (name.StartsWith('.') || name.StartsWith('$')) continue;

                        var ext = Path.GetExtension(file).ToLower();
                        if (exts.Count != 0 && !exts.Contains(ext)) continue;

                        buf.Add(file);
                    }
                    buf.Sort();
                    foreach (var file in buf)
                    {
                        var name = file.Substring(curDirLength);
                        options.Add(name);
                        optionPath.Add(file);
                    }
                }

                int index = 0;
                if (!io.SingleSelect(curDir, options.ToArray(), ref index)) return false;
                var path = optionPath[index];

                if (path == cancelID) return true;
                else if (path == newFileID)
                {
                    String fileName = null;
                    if (!io.InputString(chinese ? "输入文件名" : "Input file name", ref fileName)) return false;
                    if (String.IsNullOrEmpty(fileName)) io.Print(chinese ? "无效输入" : "Invalid input.");
                    if (SaveSuffix != null && !fileName.ToLower().EndsWith(SaveSuffix)) fileName += SaveSuffix;
                    result = curDirWithSeparator + fileName;
                    return true;
                }
                else if (path == newDirID)
                {
                    String dirName = null;
                    if (!io.InputString(chinese ? "输入文件夹名" : "Input folder name", ref dirName)) return false;
                    if (String.IsNullOrEmpty(dirName)) io.Print(chinese ? "无效输入" : "Invalid input.");
                    var newDirPath = curDirWithSeparator + dirName;
                    try
                    {
                        Directory.CreateDirectory(newDirPath);
                        curDir = newDirPath;
                    }
                    catch (Exception) { io.Print(chinese ? "创建文件夹失败。" : "Create folder failed."); }
                }
                else if (path == selectDirID)
                {
                    result = curDir;
                    return true;
                }
                else if (Directory.Exists(path))
                {
                    curDir = path;
                }
                else
                {
                    if (Type == LocalFileChooserType.SaveFile)
                    {
                        bool confirmOverwrite = false;
                        if (!io.Confirm(chinese ? "文件已存在，是否覆盖？" : "The file already exists. Do you want to replace it?", ref confirmOverwrite)) return false;
                        if (!confirmOverwrite) return true;
                    }
                    result = path;
                    return true;
                }
            }
        }

        private bool chinese = Agency.GetAppLanguage() == Language.Chinese;
    }
}